package com.huayi.datagovernance.utils;


import com.huayi.datagovernance.dao.master.TYDao;
import com.huayi.datagovernance.dto.DeviceCreateDto;
import com.huayi.datagovernance.dto.Point;
import com.huayi.datagovernance.dto.ShapeDto;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static java.lang.Math.PI;

@Component
public class ShapeUtil {

    @Autowired
    private TYDao tyDao;

    public String dealAddDeviceShape(DeviceCreateDto device, Map<String, String> tableMsg, List<Double> offset) {
        if(device.getPoints()==null||device.getPoints().size()<1){
            return null;
        }
        StringBuffer shape = new StringBuffer();

        // 如果没有类型则不处理
        if(tableMsg.get("geotype") == null){
            return shape.toString();
        }

        Map<String, String> type = new HashMap<String, String>(){{
            put("2001", "POINT"); // 点 POINT(0 0)
            put("2002", "LINESTRING"); // 线 LINESTRING(0 0,1 1,1 2)
            put("2003", "POLYGON");// 面 POLYGON((0 0,4 0,4 4,0 4,0 0),(1 1, 2 1, 2 2, 1 2,1 1))
        }};
        List<Point> points1=device.getPoints();
        for(Point point:points1){
            if(offset==null){
                point.setX(point.getX().doubleValue());
                point.setY(point.getY().doubleValue());
            }
            else {
                point.setX(point.getX().doubleValue()+offset.get(0));
                point.setY(point.getY().doubleValue()+offset.get(1));
            }

        }

        String geotype = String.valueOf(tableMsg.get("geotype"));
        // 点，线 则处理 point里的值
        if("2001".equals(geotype) || "2002".equals(geotype)){
            StringBuffer points = new StringBuffer();
            for(Point point : points1){
                points.append(point.getX()).append(" ");
                points.append(point.getY()).append(",");
            }

            // 去掉最后面的,号
            if(points.length() > 0){
                points.deleteCharAt(points.length() - 1);
                shape.append(" ST_GeomFromText ( '" + type.get(geotype) + "(" + points.toString() + ")' ) ");
            }
        }else if("2003".equals(geotype)){// 处理面
            if(points1.size() <= 0){
                return shape.toString();
            }

            shape.append(" ST_GeomFromText ( '" + type.get(geotype) + "( ");
            // 定义每个面的点格式变量
            int[] faceLength = device.getFaceLength();
            int lastSize = 0;
            for(int i=0;i<faceLength.length;i++){

                StringBuffer points = new StringBuffer();
                for(int j=lastSize;j<lastSize+faceLength[i];j++){
                    // 防止数组越界
                    if(j < points1.size()){
                        points.append(points1.get(j).getX()).append(" ");
                        points.append(points1.get(j).getY()).append(",");
                    }
                }
                // 去掉最后面的,号
                if(points.length() > 0){
                    shape.append("(");

                    points.deleteCharAt(points.length() - 1);
                    shape.append(points.toString());

                    if(i == (faceLength.length-1)){
                        shape.append(")");
                    }else{
                        shape.append("),");
                    }
                }

                // 记录上一个面的点个数
                lastSize += faceLength[i];
            }

            shape.append(") ' ) ");
        }

        return shape.toString();
    }


    /**
     * 处理shape字段里的坐标信息
     * @param shape
     * 点 POINT(0 0)
     * 线 LINESTRING(0 0,1 1,1 2)
     * 面 POLYGON((0 0,4 0,4 4,0 4,0 0),(1 1, 2 1, 2 2, 1 2,1 1))
     */
    public ShapeDto dealWithShape(String shape, List<Double> offset){
        ShapeDto shapeMsg = new ShapeDto();
        List<Point> points = new ArrayList<>();

        // 如果shape字段为空则不处理直接返回
        if(StringUtils.isEmpty(shape)){
            shapeMsg.setPoints(new ArrayList<>());
            shapeMsg.setFaceLength(new int[0]);
            shapeMsg.setType("");
            return shapeMsg;
        }

        // 获取图形类型
        String type = shape.substring(0, shape.indexOf("("));
        // 去掉外层的()
        String actualStr = shape.substring(shape.indexOf("(") + 1, shape.lastIndexOf(")"));
        if("POINT".equals(type) || "LINESTRING".equals(type)){
            // 点和线去掉()后就是实际坐标信息了
            points.addAll(dealShapeSinglePoints(actualStr,offset));
        }else if("POLYGON".equals(type)){
            actualStr = shape.substring(shape.indexOf("((") + 2, shape.lastIndexOf("))"));
            points.addAll(dealShapeSinglePoints(actualStr,offset));
            // 面去掉()后则为每个面的信息例如：(0 0,4 0,4 4,0 4,0 0),(1 1, 2 1, 2 2, 1 2,1 1)
           /* String[] polygonStrs = actualStr.split(",");
            int[] faceLength = new int[polygonStrs.length];
            // 循环处理每个面的信息
            for(int i=0;i<polygonStrs.length;i++){
                String pointStr = polygonStrs[i].substring(polygonStrs[i].indexOf("(") + 1, polygonStrs[i].indexOf(")"));
                List<Point> pointList = dealShapeSinglePoints(pointStr);
                points.addAll(pointList);
                faceLength[i] = pointList.size();
            }*/
        }

//        // 假如是转思极的话则不需要处理数据，已经处理过保存在数据库里了
//        if(!"4".equals(csys)){
//            if(!"3".equals(csys)){
//                // 处理偏移量
//                points = GeoUtil.offsetPointsReduce(points);
//            }
//
//            // 将大地2000坐标系的坐标点转成其他坐标系返回给前端
//            points = gis2000ConverterOthers(points, csys);
//        }else{
//            points = GeoUtil.mercator2LngLat(points);
//        }

        shapeMsg.setPoints(points);
        shapeMsg.setType(type);
        return shapeMsg;
    }

    private static List<Point> dealShapeSinglePoints(String pointStr,List<Double> offset){
        List<Point> points = new ArrayList<>();

        // 从第一个（截取到第一个）
        if(StringUtils.isNotEmpty(pointStr)){
            String[] pointsArray = pointStr.split(",");
            for(String item : pointsArray){
                String[] xy = item.split(" ");
                if(xy.length == 2){
                    Point temp = new Point();
                    if(offset!=null){
                        temp.setX(Double.parseDouble(xy[0])-offset.get(0));
                        temp.setY(Double.parseDouble(xy[1])-offset.get(1));
                    }
                    else {
                        temp.setX(Double.parseDouble(xy[0]));
                        temp.setY(Double.parseDouble(xy[1]));
                    }
                    points.add(temp);
                }
            }
        }


        return points;
    }

    /**
     * 摩卡多转坐标
     */
    public static Point mercator2LngLat(double gisx, double gisy) {
        double[] xy = new double[2];
        double x = gisx / 20037508.34 * 180;
        double y = gisy / 20037508.34 * 180;
        y = 180 / PI * (2 * Math.atan(Math.exp(y * PI / 180)) - PI / 2);

        return new Point(x, y);
    }
    public static Point mercator2LngLat(Point point) {
        return mercator2LngLat((double)point.getX(), (double)point.getY());
    }

    public static List<Point> mercator2LngLat(List<Point> points) {
        List<Point> newPoints = new ArrayList<>();
        for(Point point : points){
            newPoints.add(mercator2LngLat(point));
        }
        return newPoints;
    }

    /**
     * double数值保留小数点
     * @param value
     * @param digit
     * @return
     */
    public static double interceptDigit(double value, int digit){
        BigDecimal b = new BigDecimal(value);
        return b.setScale(digit, BigDecimal.ROUND_HALF_UP).doubleValue();
    }

    /**
     * 功能介绍：获取数据库中经纬度坐标的偏移量
     */

    public List<Double> getOffSet() {
        double OFFSETX = 0;
        double OFFSETY = 0;
//        double OFFSETX =  0.002;
//        double OFFSETY = 0.003;
        List<Double> doubleList = new ArrayList<Double>();
        //查询偏移量sql语句
//		String sql = "SELECT t.servicename ,t.serviceurl FROM conf.conf_serviceaddress t WHERE t.servicename in('OFFSETX','OFFSETY')";
        List<Map<String, Object>> list = tyDao.queryOffSet();
        if(list != null) {
            for (Map<String, Object> map : list) {
                if ("OFFSETX".equals(map.get("servicename"))) {
                    OFFSETX = Double.parseDouble(map.get("serviceurl") == null ? "0" : map.get("serviceurl").toString());
                }
                if ("OFFSETY".equals(map.get("servicename"))) {
                    OFFSETY = Double.parseDouble(map.get("serviceurl") == null ? "0" : map.get("serviceurl").toString());
                }
            }
        }
        doubleList.add(OFFSETX);
        doubleList.add(OFFSETY);
        return doubleList;
    }


    public List<Point> setPoints(List<Point> points,double x ,double y){
        Point point =new Point();
        point.setX(x);
        point.setY(y);
        points.add(point);
        return points;
    }

    public List<Point> setPoints(List<Point> points,double x ,double y,double x1,double y1){
        Point point =new Point();
        point.setX(x);
        point.setY(y);
        points.add(point);
        Point point1 =new Point();
        point1.setX(x1);
        point1.setY(y1);
        points.add(point1);
        return points;
    }
    public List<Point> setPoints(List<Point> points,double x ,double y,double x1,double y1,double x2,double y2){
        Point point =new Point();
        point.setX(x);
        point.setY(y);
        points.add(point);
        Point point1 =new Point();
        point1.setX(x1);
        point1.setY(y1);
        points.add(point1);
        Point point2 =new Point();
        point2.setX(x2);
        point2.setY(y2);
        points.add(point2);
        return points;
    }


    public String dealAddDeviceShape(List<Point> pointList, String geotype, List<Double> offset) {
        if(pointList==null||pointList.size()<1){
            return null;
        }
        StringBuffer shape = new StringBuffer();

        // 如果没有类型则不处理
        if(StringUtils.isEmpty(geotype)){
            return shape.toString();
        }

        Map<String, String> type = new HashMap<String, String>(){{
            put("2001", "POINT"); // 点 POINT(0 0)
            put("2002", "LINESTRING"); // 线 LINESTRING(0 0,1 1,1 2)
            put("2003", "POLYGON");// 面 POLYGON((0 0,4 0,4 4,0 4,0 0),(1 1, 2 1, 2 2, 1 2,1 1))
        }};
        List<Point> points1=pointList;
        for(Point point:points1){
            if(offset==null){
                point.setX(point.getX().doubleValue());
                point.setY(point.getY().doubleValue());
            }
            else {
                point.setX(point.getX().doubleValue()+offset.get(0));
                point.setY(point.getY().doubleValue()+offset.get(1));
            }
        }

        // 点，线 则处理 point里的值
        if("2001".equals(geotype) || "2002".equals(geotype)){
            StringBuffer points = new StringBuffer();
            for(Point point : points1){
                points.append(point.getX()).append(" ");
                points.append(point.getY()).append(",");
            }

            // 去掉最后面的,号
            if(points.length() > 0){
                points.deleteCharAt(points.length() - 1);
                shape.append(" ST_GeomFromText ( '" + type.get(geotype) + "(" + points.toString() + ")' ) ");
            }
        }else if("2003".equals(geotype)){// 处理面
            if(points1.size() <= 0){
                return shape.toString();
            }
            //POLYGON((116.381420664612 39.8968384954551,116.381600327668 39.8968384954551,116.381600327668 39.8966588323983,116.381420664612 39.8966588323983,116.381420664612 39.8968384954551))
            shape.append(" ST_GeomFromText ( '" + type.get(geotype) + " ((");

            StringBuffer points = new StringBuffer();
            for(Point point : points1){
                points.append(point.getX()).append(" ");
                points.append(point.getY()).append(",");
            }
            shape.append(points.substring(0,points.length()-1));
            shape.append("))') ");
        }

        return shape.toString();
    }

    public String geoTypeToFourFigure(String geoType){
        if (geoType == null){
            return "";
        }
        String gtype;
        switch (geoType) {
            case "1":
                gtype = "2001";
                break;
            case "2":
            case "4":
            case "5":
            case "6":
            case "7":
            case "8":
            case "9":
            case "10":
            case "11":
                gtype = "2002";
                break;
            case "3":
                gtype = "2003";
                break;
            default:
                gtype = geoType;
//                gtype = "";
                break;
        }
        return gtype;
    }
}
